package com.fastwire.carriere.hibernate.daoimpl;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import com.fastwire.carriere.common.util.CommonLogger;
import com.fastwire.carriere.common.util.StringUtil;
import com.fastwire.carriere.dao.DAOException;
import com.fastwire.carriere.dao.NEDao;
import com.fastwire.carriere.inventory.entity.Equipment;
import com.fastwire.carriere.inventory.entity.NetworkElement;
import com.fastwire.carriere.inventory.entity.NetworkEntity;
import com.fastwire.carriere.inventory.vo.NetworkElementVo;

// TODO: Auto-generated Javadoc
/**
 * The Class NEDaoImpl.
 */
public class NEDaoImpl extends AbstractDAOImpl implements NEDao {

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.fastwire.carriere.dao.NEDao#saveOrUpdateNE(com.fastwire.carriere.
	 * inventory.entity.NetworkElement)
	 */
	@Override
	public void saveOrUpdateNE(NetworkElement networkElement)
			throws DAOException {
		super.saveOrUpdate(networkElement);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fastwire.carriere.dao.NEDao#findAllNEs()
	 */
	@Override
	public List<NetworkElement> findAllNEs() throws DAOException {
		DetachedCriteria criteria = DetachedCriteria
				.forClass(NetworkElement.class);
		criteria = criteria.add(getStatusCriteria());
		return getHibernateTemplate()
				.findObjsByCriteria(criteria, false, false);
	}

	@Override
	public void invalidateAll() throws DAOException {

		Session session = HibernateUtil.openSession();
		try {
			session.beginTransaction();
			Criteria executableCriteria = session
					.createCriteria(NetworkElement.class);
			executableCriteria.add(getStatusCriteria());
			executableCriteria.setFetchSize(1000);
			ScrollableResults scrollableResults = executableCriteria
					.scroll(ScrollMode.FORWARD_ONLY);
			int count = 0;
			while (scrollableResults.next()) {
				Object object = scrollableResults.get(0);

				NetworkElement ne = (NetworkElement) object;
				ne.invalidate();

				for (Equipment eq : ne.getEquipments()) {
					eq.invalidate();
				}

				if (++count % 50 == 0) {
					session.flush();
					session.clear();
				}

			}
			session.flush();
			session.clear();
			session.getTransaction().commit();

		} catch (Exception ex) {
			if (session.getTransaction().isActive()) {
				session.getTransaction().rollback();
			}
			throw new DAOException(ex);
		} finally {
			HibernateUtil.close(session);

		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fastwire.carriere.dao.NEDao#findNEbyName(java.lang.String)
	 */
	@Override
	public NetworkElement findNEbyName(String neName) throws DAOException {
		DetachedCriteria criteria = DetachedCriteria
				.forClass(NetworkElement.class);

		Criterion nameCriterion = Restrictions.eq("emsNativeName", neName);
		Criterion nativeNameCriterion = Restrictions.eq("name", neName);
		criteria.add(Restrictions.or(nameCriterion, nativeNameCriterion));
		criteria.setFetchMode("equipments", FetchMode.JOIN);
		criteria = criteria.add(getStatusCriteria());

		List objList = getHibernateTemplate().findObjsByCriteria(criteria, false, true);

		if (!StringUtil.isNullOrEmptyList(objList))
			return (NetworkElement) objList.get(0);
		else {
			return null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fastwire.carriere.dao.NEDao#findAllNETypes()
	 */
	@Override
	public List findAllNETypes() throws DAOException {

		DetachedCriteria criteria = DetachedCriteria
				.forClass(NetworkElement.class);
		criteria = criteria.add(getStatusCriteria());
		criteria.setProjection(Projections.distinct(Projections
				.property("neType")));
		return getHibernateTemplate().findObjsByCriteria(criteria, true, true);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.fastwire.carriere.dao.NEDao#findNEbySearchCriteria(com.fastwire.carriere
	 * .inventory.vo.NetworkElementVo)
	 */
	@Override
	public List findNEbySearchCriteria(NetworkElementVo neVo)
			throws DAOException {

		DetachedCriteria criteria = DetachedCriteria
				.forClass(NetworkElement.class);
		criteria = criteria.add(getStatusCriteria());

		if (!StringUtil.isEmptyString(neVo.getNativeEmsName())) {
			criteria.add(getWildCardCriterion("emsNativeName",
					neVo.getNativeEmsName()));
		}

		if (!StringUtil.isEmptyString(neVo.getNeType())) {
			criteria.add(Restrictions.eq("neType", neVo.getNeType()));
		}

		criteria.addOrder(Order.asc("emsNativeName"));

		criteria.setProjection(Projections.distinct(Projections
				.property("emsNativeName")));

		return getHibernateTemplate().findObjsByCriteria(criteria, true, false);

	}

	// modified by Jun on 20120416
	@Override
	public void invalidateAll(List objList) throws DAOException {
		/*
		if (objList == null) {
			return;
		}
		for (Object obj : objList) {
			NetworkEntity ne = (NetworkEntity) obj;
			ne.invalidate();
		}
		mergeAll(objList);
		*/
		
		if (null == objList || objList.size() <= 0) {
			return;
		}
		
		Session session = HibernateUtil.openSession();
		Transaction tx = session.beginTransaction();

		int count = 0;
		int neNo = 0;

		try {
			for (Object obj : objList) {				
				((NetworkEntity)obj).invalidate();
				
				session.merge(obj);
				//session.update(obj);
				
				if (++count % 50 == 0) {
					session.flush();
					session.clear();
				}
				CommonLogger.debug(this, "total entities in session" + 
									session.getStatistics().getEntityCount());
				
				if (obj instanceof NetworkElement) {
					CommonLogger.info(this, "handle tb_network_element:" + neNo++);
				}
			}

			tx.commit();
			
		} catch (Exception ex) {
			if(tx.isActive()) {
				tx.rollback();
			}
			throw new DAOException(ex);
		} finally {
			HibernateUtil.close(session);
		}		
	}

}
